/*
 JS中常用的循环操作语句
   + for
   + while「do\while」
   + 数组的迭代方法：forEach、map、reduce、reduceRight、filter、find、findIndex、some、every
   + for in
   + for of
   + ...

 项目中选择哪一种循环方案？
   @1 首先看性能「好(高)->坏(低)」
     for、while -> 数组的迭代方法 -> for of -> for in
   @2 其次看各循环的作用
     + for：一般指定起始和结束的条件进行循环，可用来创建指定次数的循环 或 迭代数组/类数组中的内容
     + while：一般用于不确定具体执行的次数
     + for of：直接迭代数据中的内容
     + for in：可以迭代对象
   @3 最后优先使用函数式编程「简化操作，实现代码的低耦合高内聚」
 */
// 需求5：迭代对象中的每一项「一般的需求都是只迭代私有的即可，不考虑公有的成员」
/* Object.prototype.AAA = 'AAA';
let obj = {
    name: '挖呀挖呀挖',
    x: 100,
    1: 20,
    0: 30,
    [Symbol('AA')]: '哇咔咔'
};
let keys = Reflect.ownKeys(obj);
keys.forEach(key => {
    console.log(key, obj[key]);
}); */

/*
Object.keys(obj)：获取对象 “私有的”、“可枚举的”、“非Symbol类型的” 成员
Object.getOwnPropertyNames(obj)：获取对象 “私有的”、“非Symbol类型的” 成员「不管枚举性」
Object.getOwnPropertySymbols(obj)：获取对象 “私有的”、“Symbol类型的” 成员「不管枚举性」
获取对象所有的“私有”成员「不考虑类型和枚举的限制」
let keys = Object.getOwnPropertyNames(obj).concat(Object.getOwnPropertySymbols(obj));
console.log(keys);
简单的办法
Reflect.ownKeys(obj) ES6提供的这个API，可以直接获取对象所有的私有成员
*/

/*
 for/in循环的问题
   + 不仅仅会迭代私有的属性，还会按照原型链去所属类的原型对象上查找「一直遍历到Object.prototype为止」-->所以for/in循环的性能很差！！
   + 只能迭代 “可枚举” && “非Symbol类型” 的成员 --> 具有迭代限制
   往后想要迭代对象的成员，我们尽可能的不要使用for/in循环！！

 对象成员的类型：字符串、Symbol类型
 对象成员的规则：
   查看规则：
     Object.getOwnPropertyDescriptor(obj,key)
     或者
     Object.getOwnPropertyDescriptors(obj)
   + configurable 是否可删除
   + writable 是否可修改
   + enumerable 是否可枚举
   + value 成员值
 @1 默认情况下，基于 obj.xxx 或者 在大括号中 设置的成员，其相应规则都是 true
 @2 一般情况下，浏览器内置的成员，其规则：enumerable=false（不可枚举），其余的都是true
 @3 我们还可以基于 Object.defineProperty 设置成员及其规则
   如果成员存在，我们可以为其修改规则
    Object.defineProperty(obj,'name',{
        enumerable:false
    })
   如果成员不存在，则新增一个成员，其默认规则都是false
    Object.defineProperty(obj,'age',{
        value:25
    })
 */
/* for (let key in obj) {
    if (!obj.hasOwnProperty(key)) break; //此操作仅仅是不让其输出公有“可枚举”的成员，但是不能完全保证让其不迭代公有成员！
    console.log(key, obj[key]);
} */

//==================
// 需求4：创建一个4位不重复的验证码
/* let area = 'qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890'; //0~61
let code = ``;
while (code.length < 4) { //只要验证码长度不足4位，我们就要一直处理
    let ran = Math.round(Math.random() * 61),
        char = area.charAt(ran);
    if (new RegExp(char, 'i').test(code)) continue;
    code += char;
}
console.log(code); */

// 需求3：迭代数组的奇数项
/* let arr = [10, 20, 30, 40, 50, 60, 70];
for (let i = 0; i < arr.length; i += 2) {
    console.log(arr[i]);
} */
/* // 这样处理：每一项都被迭代了，只不过在奇数项才输出
arr.forEach((item, index) => {
    if (index % 2 === 0) {
        console.log(item);
    }
}); */

// 需求2：依次迭代数组/伪数组每一项
/* let arr = [10, 20, 30];
arr.forEach((item, index) => {
    console.log(item, index);
}); */

// 需求1：循环五次
// for (let i = 0; i < 5; i++) { }  //命令式编程
/* new Array(5).fill(null).forEach(() => { //函数式编程
    console.log('AA');
}); */

//======================
/* let arr = [10, 20, 30, 40, 50];
_.each(arr, function (item, index) {
    console.log(this, item, index);
    if (index > 2) return false;
}); */

/* let list = document.querySelectorAll('*');
_.each(list, (item, index) => {
    console.log(item, index);
}); */

/* let obj = {
    name: '挖呀挖呀挖',
    x: 100,
    1: 20,
    0: 30,
    [Symbol('AA')]: '哇咔咔'
};
_.each(obj, (value, key) => {
    console.log(value, key);
    // if (key === 'name') return false;
}); */

_.each(5, (item, index) => {
    console.log(item, index);
});

_.each("珠峰培训", (item, index) => {
    console.log(item, index);
});